#include "TestMd5.h"
#include <QtWidgets/QApplication>

#include <Windows.h>
#include <Wincrypt.h>
#include <iostream>
#include <iomanip>

#pragma comment(lib, "Crypt32.lib")

bool CalculateMD5(std::wstring &_wstrFileName, BYTE* hash)
{
	HANDLE hFile = CreateFile(_wstrFileName.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
	if (hFile == INVALID_HANDLE_VALUE)
	{
		std::cerr << "Error opening file\n";
		return false;
	}

	HCRYPTPROV hProv;
	HCRYPTHASH hHash;
	if (!CryptAcquireContext(&hProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT) ||
		!CryptCreateHash(hProv, CALG_MD5, 0, 0, &hHash))
	{
		CloseHandle(hFile);
		std::cerr << "Error creating hash context\n";
		return false;
	}

	const DWORD bufferSize = 4096;
	BYTE buffer[bufferSize];
	DWORD bytesRead = 0;
	while (ReadFile(hFile, buffer, bufferSize, &bytesRead, NULL) && bytesRead > 0)
	{
		if (!CryptHashData(hHash, buffer, bytesRead, 0))
		{
			CryptDestroyHash(hHash);
			CryptReleaseContext(hProv, 0);
			CloseHandle(hFile);
			std::cerr << "Error hashing data\n";
			return false;
		}
	}

	DWORD hashSize = 16;
	if (!CryptGetHashParam(hHash, HP_HASHVAL, hash, &hashSize, 0))
	{
		CryptDestroyHash(hHash);
		CryptReleaseContext(hProv, 0);
		CloseHandle(hFile);
		std::cerr << "Error getting hash value\n";
		return false;
	}

	CryptDestroyHash(hHash);
	CryptReleaseContext(hProv, 0);
	CloseHandle(hFile);
	return true;
}

bool CompareMD5(const BYTE* hash1, const BYTE* hash2)
{
	for (int i = 0; i < 16; ++i)
	{
		if (hash1[i] != hash2[i])
		{
			return false;
		}
	}
	return true;
}


int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    TestMd5 w;
    w.show();
    return a.exec();
}
